package com.example.belong.testgetread;

import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * Created by Administrator on 2018/7/5 0005.
 * 自定义红包控件
 *
 * @see
 */

public class GetRadBoxView extends View implements Runnable {
    private Context mContext;
    private Canvas mCanvas;
    private int mWidthAll;//总宽度
    private int mHeightAll;//总高度
    private float mWidth;//显示区域宽度
    private float mHeight;//显示区域高度
    /*** *******************************图片*****/
    /*** 展示的方块图片*/
    private Bitmap mBoxBitmap;
    /*** 展示的图片上的数据集合*/
    private List<String> msgList;
    /*** 方块的位置 区域*/
    private List<RectF> mRects;
    /*** 生成最低线的位置比例 0~1*/
    private PointF showLine = new PointF(1f, 0.6f);
    /*** 触发最高线的位置比例 0~1*/
    private PointF triggerLine = new PointF(1f, 0.8f);
    /*** 触发的box 边缘比例 0~1*/
    private PointF triggerBoxLine = new PointF(1f, 1f);
    /*** 删除的索引集合*/
    private List<Integer> delBox;
//    /*** 是否 触发/显示 逆转  初始为上左显示，下右触发*/
//    private boolean isTriggerReverse=false;
    /*** 离散度 0~1*/
    private float concentration = 1f;
    /*** 单个方块大小比例 0~1*/
    private float boxSize = 1f;
    /*** 实际大小*/
    private PointF actualSize;
    /*** *******************************文字*****/
    /*** 文字画笔*/
    private Paint mTextPaint = new Paint();
    /*** 文字颜色*/
    private String textColor = "#000000";
    /*** 文字大小*/
    private float textSize = 25f;
//    /*** 文字大小是否强制一致*/
//    private boolean isTextAllSize = false;
    /*** 文字中心位置与图片中心的偏移比例 */
    private PointF textOffset = new PointF(0f, 0f);
    /*** 文字中心点的集合*/
    private List<PointF> mTextPointList;
    /*** 当前选中的box位置*/
    private int selectBoxPoint = -1;
    //当前移动box图片的区域
    private RectF checkRectF;
    //当前移动box文字的区域
    private PointF checkPointF;
    //文字高度
    private float textHeight;
    //删除后的回调
    private GetRadBoxCallBack mCall;
    //是否开启动画
    private boolean isAnimator = true;
    //变幻时的值
    private float[] fraction = {0, 0, 0};
    private ValueAnimator animator;
    private Random random;//随机数生成器
    /**
     * 动画的属性,运动的极限距离
     * 最初x，最终x，最初y，最终y，最初大小，最终大小
     */
    private float[] animatorData = {-0.5f, 0.5f, -1, 1, -0.2f, 0.1f};
    /*** 动画时间*/
    private long animatorTime = 1000;


    public GetRadBoxView(Context context) {
        super(context);
        init(context);
    }

    public GetRadBoxView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public GetRadBoxView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        setClickable(true);
        mContext = context;
        if (mContext instanceof GetRadBoxCallBack) {
            mCall = (GetRadBoxCallBack) mContext;
        }
        msgList = new ArrayList<>();
        mRects = new ArrayList<>();
        mTextPointList = new ArrayList<>();
        delBox = new ArrayList<>();
        actualSize = new PointF();
        checkRectF = new RectF();
        checkPointF = new PointF();
        random = new Random();
        initTextPaint(mTextPaint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidthAll = getMeasuredWidth();
        mHeightAll = getMeasuredHeight();
        mWidth = showLine.x * mWidthAll;
        mHeight = showLine.y * mHeightAll;
    }

    /**
     * 添加回调
     */
    public void setmCall(GetRadBoxCallBack mCall) {
        this.mCall = mCall;
    }

    /**
     * 动画的属性,运动的极限距离
     * 左负右正
     * 最初x，最终x，最初y，最终y，最初大小，最终大小
     */
    public void setAnimatorData(float[] animatorData) {
        this.animatorData = animatorData;
    }

    /**
     * 设置单次动画时间
     */
    public void setAnimatorTime(long animatorTime) {
        this.animatorTime = animatorTime;
    }

    /**
     * 是否开启动画
     */
    public void setAnimator(boolean animator) {
        isAnimator = animator;
    }

    /**
     * 生成最低线的位置比例 0~1
     * 默认 1, 0.6
     */
    public void setShowLine(PointF showLine) {
        this.showLine = showLine;
    }

    /**
     * 触发最高线的位置比例 0~1
     * 默认 1，0.8
     */
    public void setTriggerLine(PointF triggerLine) {
        this.triggerLine = triggerLine;
    }

    /**
     * 触发的box 边缘比例 0~1
     * 默认 1,1
     */
    public void setTriggerBoxLine(PointF triggerBoxLine) {
        this.triggerBoxLine = triggerBoxLine;
    }

    /**
     * 离散度 0~1
     * 默认 1
     */
    public void setConcentration(float concentration) {
        this.concentration = concentration;
    }

    /**
     * 单个方块大小比例 0~1
     * 默认 1
     */
    public void setBoxSize(float boxSize) {
        this.boxSize = boxSize;
    }

    /**
     * 文字颜色值
     * 默认 "#000000"
     */
    public void setTextColor(String textColor) {
        this.textColor = textColor;
    }

    /**
     * 文字大小
     * 默认 25
     */
    public void setTextSize(float textSize) {
        this.textSize = textSize;
    }

    /**
     * 文字中心位置与图片中心的偏移比例 0~1
     * 不能为 0
     * 默认 0,0
     */
    public void setTextOffset(PointF textOffset) {
        this.textOffset = textOffset;
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        mCanvas = canvas;
        draw(mRects, mTextPointList);
        if (mHeightAll != 0 && isAnimator&&
                animator != null && !animator.isStarted()) {
            animator.start();
        }
    }

    /**
     * 绘制方法
     *
     * @param rects:方块位置集合
     * @param textPointList:文字位置集合
     */
    private void draw(List<RectF> rects, List<PointF> textPointList) {
//        mCanvas.drawLine(0, triggerLine.y * mHeightAll, mWidthAll, triggerLine.y * mHeightAll, mTextPaint);
//        mCanvas.drawLine(triggerLine.x * mWidthAll, 0, triggerLine.x * mWidthAll, mHeightAll, mTextPaint);
        for (int i = 0; i < rects.size(); i++) {
            if (delBox.contains(i)) {
                continue;
            }
            if (selectBoxPoint != -1 && selectBoxPoint == i) {
                mCanvas.drawBitmap(mBoxBitmap, null, checkRectF, null);
                mCanvas.drawText(msgList.get(i), checkPointF.x, checkPointF.y, mTextPaint);
            } else {
                RectF rectF = rects.get(i);
                float x = fraction[0] * rectF.width();
                float y = fraction[1] * rectF.height();
                float zx = fraction[2] * rectF.width();
                float zy = fraction[2] * rectF.height();
                rectF.left += x - zx;
                rectF.right += x + zx;
                rectF.top += y - zy;
                rectF.bottom += y + zy;
//                Log.e("------bbb",i+"----"+fraction.toString()+"-----"+rectF.top+"------"+rectF.bottom);
                mCanvas.drawBitmap(mBoxBitmap, null, rectF, null);
                PointF pointF = textPointList.get(i);
                mCanvas.drawText(msgList.get(i), pointF.x + x, pointF.y + y, mTextPaint);
                rectF.left -= x - zx;
                rectF.right -= x + zx;
                rectF.top -= y - zy;
                rectF.bottom -= y + zy;
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int actionMasked = event.getActionMasked();
        if (actionMasked == MotionEvent.ACTION_MOVE) {//按下
            checkTouchMove(event);
            postInvalidate();
        } else if (actionMasked == MotionEvent.ACTION_DOWN) {//移动
            checkTouchCheck(event);
            if (!isAnimator) {
                postInvalidate();
            }
        } else if (actionMasked == MotionEvent.ACTION_UP) {//放开
            checkTouchUp();
            if (!isAnimator) {
                postInvalidate();
            }
        }
        return super.onTouchEvent(event);
    }

    /**
     * 移动时的处理
     */
    private void checkTouchMove(MotionEvent event) {
        //这次位置
        float x = event.getX(0);
        float y = event.getY(0);
        //计算更新图片的位置
        float width = checkRectF.width();
        float height = checkRectF.height();
        checkRectF.left = x - width / 2;
        checkRectF.right = x + width / 2;
        checkRectF.top = y - height / 2;
        checkRectF.bottom = y + height / 2;
        //计算更新文字的位置
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        float x1 = checkRectF.right - checkRectF.width() / 2;
        float y1 = checkRectF.bottom + (fontMetrics.descent - fontMetrics.top);
        checkPointF.x = x1+width * textOffset.x;
        checkPointF.y = y1+height * textOffset.y;
    }

    /**
     * 检测手指是否选中了, 哪个box
     */
    private void checkTouchCheck(MotionEvent motionEvent) {
        //这次位置
        float nX = motionEvent.getX(0);
        float nY = motionEvent.getY(0);
        for (int i = mRects.size() - 1; i >= 0; i--) {
            RectF rectF = mRects.get(i);
            PointF pointF = mTextPointList.get(i);

            float x = fraction[0] * rectF.width();
            float y = fraction[1] * rectF.height();
            float zx = fraction[2] * rectF.width();
            float zy = fraction[2] * rectF.height();

            float left = rectF.left + x - zx;
            float right = rectF.right + x + zx;
            float top = rectF.top + y - zy;
            float bottom = rectF.bottom + y + zy;

            float pointX = pointF.x + x;
            float pointY = pointF.y + y;


            float width = mTextPaint.measureText(msgList.get(i));
            float x1 = left < pointX - width / 2 ? left : pointX - width / 2;
            float x2 = right > pointX + width / 2 ? right : pointX + width / 2;
            float y1 = top < pointY - textHeight ? top : pointY - textHeight;
            float y2 = bottom > pointY ? bottom : pointY;

            if (nX >= x1 && nX <= x2 && nY >= y1 && nY <= y2) {
                selectBoxPoint = i;
                checkRectF.top = top;
                checkRectF.bottom = bottom;
                checkRectF.left = left;
                checkRectF.right = right;
                checkPointF.x = pointX;
                checkPointF.y = pointY;
                break;
            }
        }
    }

    /**
     * 手指离开时的操作
     */
    private void checkTouchUp() {
        //判断是否删除
        float triggerY = mHeightAll * triggerLine.y;
        float triggerX = mWidthAll * triggerLine.x;
//        Log.e("-------","====="+triggerX+"====="+triggerY
//                +"====="+checkRectF.bottom*triggerBoxLine.y
//                +"======="+checkRectF.right*triggerBoxLine.x);
        if (checkRectF.bottom * triggerBoxLine.y > triggerY
                || checkRectF.right * triggerBoxLine.x > triggerX) {//可以删除
            if (selectBoxPoint != -1 && !delBox.contains(selectBoxPoint)) {
                delBox.add(selectBoxPoint);
            }
            if (mCall != null&&selectBoxPoint!=-1) {
                mCall.delBox(delBox, selectBoxPoint);
            }
        }
        selectBoxPoint = -1;
    }

    /**
     * 初始化画笔
     */
    private void initTextPaint(Paint paint) {
        paint.setColor(Color.parseColor(textColor));
        //基本设置
        //设置画笔宽度
        paint.setStrokeWidth(2);
        //指定是否使用抗锯齿功能，如果使用，会使绘图速度变慢
        paint.setAntiAlias(true);
        //绘图样式，对于设文字和几何图形都有效
        paint.setStyle(Paint.Style.FILL);

        //设置文字对齐方式，取值：align.CENTER、align.LEFT或align.RIGHT
        paint.setTextAlign(Paint.Align.CENTER);
        //设置文字大小
        paint.setTextSize(textSize);

        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        textHeight = fontMetrics.descent - fontMetrics.top;

        //样式设置
//        paint.setFakeBoldText(true);//设置是否为粗体文字
//        paint.setUnderlineText(true);//设置下划线
//        paint.setTextSkewX((float) -0.25);//设置字体水平倾斜度，普通斜体字是-0.25
//        paint.setStrikeThruText(true);//设置带有删除线效果a
        //设置拉伸
//        paint.setTextScaleX(2);//只会将水平方向拉伸，高度不会变
    }

    /**
     * 添加展示数据
     * @param imgData：展示的图片
     * @param msgDatas：文字内容
     */
    public void setImgAddData(@NonNull Bitmap imgData, List<String> msgDatas) {
        msgList.clear();
        mRects.clear();
        mTextPointList.clear();
        delBox.clear();
        msgList.addAll(msgDatas);
        mBoxBitmap = imgData;
    }

    /**
     * 初始化，启动必须调用的方法
     */
    public void initAll() {
        new Thread(this).start();
    }


    /**
     * 初始化点
     *
     * @param size    ：点个数
     * @param boxBitmap：点图片
     */
    private void initPoint(int size, Bitmap boxBitmap) {

        int width = boxBitmap.getWidth();
        int height = boxBitmap.getHeight();
        //图片高宽哪个大
        int imgMax = Math.max(height, width);
//        Log.e("----123",mHeight+"-----"+mWidth+"------"+width+"----"+height+"----"+imgMax);
        int num = 0;
        //获取实际图片大小
        while (num < size) {
            num = (int) ((mHeight / imgMax) * (mWidth / imgMax));
            imgMax--;
        }
        imgMax++;
        //纵向与横向个数
        int numH = (int) (mHeight / imgMax);
        int numW = (int) (mWidth / imgMax);
        int max = Math.max(numH, numW);
        int min = Math.max(numH, numW);
        int step = 0;
        while (max * min > size) {
            step++;
            if (max == 1 || min == 1) {
                break;
            }
            if (step % 2 == 0) {
                min--;
            } else {
                max--;
            }
        }
        if (max * min < size) {
            if (step % 2 == 0) {
                min++;
            } else {

                max++;
            }
        }
        //得到充分的 纵向与横向个数
        if (numW > numH) {
            numW = max;
            numH = min;
        } else {
            numH = max;
            numW = min;
        }
        //单个空间
        float totalH = mHeight / numH;
        float totalW = mWidth / numW;
        //纵向与横向可偏移量
        float offsetH = (mHeight - imgMax * numH) / numH;
        float offsetW = (mWidth - imgMax * numW) / numW;
//        Log.e("----124",numW+"-----"+numH);
//        Log.e("----125",offsetW+"-----"+offsetH);
//        Log.e("----126",totalW+"-----"+totalH);
//        Log.e("----127","-----"+imgMax);
        //实际大小 变化倍数
        float min1 = Math.min((float) imgMax / height, (float) imgMax / width) * boxSize;
        actualSize.x = width * min1;
        actualSize.y = height * min1;
        //初始位置
        float x;
        float y;
        //开始确定绘制的坐标
        for (int i = 0; i < size; i++) {
            //左上角
            x = totalW * (i % numW);
            y = totalH * (i / numW);
            //开始偏移
            float offW = random.nextFloat() * offsetW * concentration;
            float offH = random.nextFloat() * offsetH * concentration;
            x = x + offW;
            y = y + offH;
            //方块绘制区域
            mRects.add(new RectF(x, y, x + actualSize.x, y + actualSize.y));
        }
    }

    /**
     * 初始化文字
     */
    private void initText() {
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        //居中样式化画笔
        for (int i = 0; i < mRects.size(); i++) {
            RectF rectF = mRects.get(i);
            float x = rectF.right - rectF.width() / 2;
            float y = rectF.bottom + (fontMetrics.descent - fontMetrics.top);
            PointF pointF = new PointF(x+rectF.width() * textOffset.x, y +rectF.height()* textOffset.y);
            mTextPointList.add(pointF);
        }
    }

    @Override
    public void run() {
        while (mHeightAll == 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        initPoint(msgList.size(), mBoxBitmap);
        initAnimator();
        initTextPaint(mTextPaint);
        initText();
        postInvalidate();
    }

    /**
     * 初始化动画
     */
    private void initAnimator() {
        if (!isAnimator) {
            return;
        }
        float[] startV = new float[]{animatorData[0], animatorData[3], animatorData[5]};
        float[] ednV = new float[]{animatorData[1], animatorData[2], animatorData[4]};
        animator = ValueAnimator.ofObject(new AnimatorValue(), startV, ednV);
        animator.setDuration(animatorTime);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setRepeatMode(ValueAnimator.REVERSE);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                fraction = (float[]) animation.getAnimatedValue();
                postInvalidate();
            }
        });
    }

    interface GetRadBoxCallBack {
        /**
         * 删除后的回调
         *
         * @param delIndex：删除的索引集合
         * @param delThis：本次删除的引索
         */
        void delBox(List<Integer> delIndex, int delThis);
    }

    /**
     * 动画的差值器
     */
    class AnimatorValue implements TypeEvaluator {
        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            float[] startV = (float[]) startValue;
            float[] endV = (float[]) endValue;
            float[] floats = new float[3];
            floats[0] = startV[0] + fraction * (endV[0] - startV[0]);
            floats[1] = startV[1] + fraction * (endV[1] - startV[1]);
            floats[2] = startV[2] + fraction * (endV[2] - startV[2]);
            return floats;
        }
    }


}
